/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.ext.echarts.util;

import cn.easyplatform.web.ext.echarts.ECharts;
import cn.easyplatform.web.ext.echarts.lib.Legend;
import cn.easyplatform.web.ext.echarts.lib.style.TextStyle;
import org.apache.commons.lang3.ArrayUtils;

import java.util.*;

/**
 * @Author Zeta
 * @Version 1.0
 */
public final class CreateModelUtils {

    /**
     * 兼容柱状图和折线图的图表创建方法
     *
     * @param echarts 图表对象
     * @param model   数据源
     */
    public final static void barlineCreateModel(ECharts echarts, List<Map> model) {

        List<Map<String, Object>> series = null; //Series属性集
        Map<String, Object> serie = null; //Serie属性
        List<Object> category = new ArrayList<>(); //分类示例
        LinkedHashMap<String, List<Map<String, Object>>> data = null;

        if (echarts.getOption().getSeries() instanceof Map) {
            serie = (Map<String, Object>) echarts.getOption().getSeries();
            series = new ArrayList<>();
            echarts.getOption().setSeries(series);
        } else if (echarts.getOption().getSeries() instanceof List) {
            series = (List) echarts.getOption().getSeries();
            serie = series.get(0);
            series.clear();
        } else if (echarts.getOption().getSeries() == null) {
            if (echarts.getOption().getBaseOption() != null) {
                serie = (Map<String, Object>) echarts.getOption().getBaseOption().getSeries();
                series = new ArrayList<>();
                echarts.getOption().setSeries(series);
            }
        }

        if (!model.isEmpty()) {

            //原设计支持3种数据解析方式，现约定只支持一种，但仍保留该设计
            if (echarts.getCreateType() != null && echarts.getCreateType().equals("byHeaderIsAxis")) {
                data = createByHeaderIsAxis(echarts, model);
            } else if (echarts.getCreateType() != null && echarts.getCreateType().equals("byHeaderIsKey")) {
                data = createByHeaderIsKey(echarts, model);
            } else {
                data = createByFieldValue(echarts, model);
            }

            if (!data.isEmpty()) {
                for (Map.Entry<String, List<Map<String, Object>>> entry : data.entrySet()) {
                    Map<String, Object> map = new HashMap<>(serie);
                    category.add(entry.getKey());
                    map.put("name", entry.getKey());
                    map.put("data", entry.getValue().toArray());
                    series.add(map);
                }

                if (!category.isEmpty() && echarts.getOption().getLegend() != null)
                    echarts.getOption().getLegend().setData(category);

                return;
            }
        }

        //数据为空时显示暂无数据
        Map<String, Object> xAxis = null;
        if (echarts.getOption().getxAxis() != null) {
            if (echarts.getOption().getxAxis() instanceof List)
                xAxis = (Map<String, Object>) ((List) echarts.getOption().getxAxis()).get(0);
            else xAxis = (Map<String, Object>) echarts.getOption().getxAxis();
            if ("data".equals(xAxis.get("data")) || echarts.getSequence().contains("xAxis")) {
                echarts.getSequence().add("xAxis");
            }
        }
        String[] str = new String[]{"查无数据"};
        xAxis.put("data", str);
        Map<String, Object> map = new HashMap<>(serie);
        map.put("name", "查无数据");
        map.put("data", 0);
        Legend legend;
        if (echarts.getOption().getLegend() != null) {
            legend = echarts.getOption().getLegend();
        } else {
            legend = new Legend();
        }
        legend.show(true);
        List list = new ArrayList(1);
        list.add("查无数据");
        legend.setData(list);
        if (echarts.getOption().getLegend() == null) {
            echarts.getOption().setLegend(legend);
        }
        series.clear();
        series.add(map);
        echarts.clearInit();
    }

    /**
     * 将列数据作为横、纵坐标和Key
     *
     * @param echarts
     * @param model
     * @return
     */
    private final static LinkedHashMap createByFieldValue(ECharts echarts, List<Map> model) {

        Map<String, Object> xAxis = null;//x轴
        Map<String, Object> yAxis = null;//y轴
        List<Object> xlist = null;
        List<Object> ylist = null;

        if (echarts.getOption().getxAxis() != null) {
            if (echarts.getOption().getxAxis() instanceof List)
                xAxis = (Map<String, Object>) ((List) echarts.getOption().getxAxis()).get(0);
            else
                xAxis = (Map<String, Object>) echarts.getOption().getxAxis();
            if ("data".equals(xAxis.get("data")) || echarts.getSequence().contains("xAxis")) {
                echarts.getSequence().add("xAxis");
                xlist = new ArrayList<>();
            }
        }
        if (echarts.getOption().getyAxis() != null) {
            if (echarts.getOption().getyAxis() instanceof List)
                yAxis = (Map<String, Object>) ((List) echarts.getOption().getyAxis()).get(0);
            else
                yAxis = (Map<String, Object>) echarts.getOption().getyAxis();
            if ("data".equals(yAxis.get("data")) || echarts.getSequence().contains("yAxis")) {
                echarts.getSequence().add("yAxis");
                ylist = new ArrayList<>();
            }
        }

        LinkedHashMap<String, List<Object>> data = new LinkedHashMap<>();
        Object[] keySet = model.get(0).keySet().toArray(); //所有字段名
        boolean flag = true; //控制标记
        for (Map map : model) {
            String xName = null;
            String yName = null;
            List<Object> objs = new ArrayList<Object>(map.values()); // 每一行的所有字段数据
            int index = 0; // 每一行数据列表的下标
            if (xlist != null) {
                if (objs.size() > index) { //列表第一个数据是xAxis
                    if (objs.get(index) == null) { //为空则跳过
                        continue;
                    }
                    xName = objs.get(index).toString();
                    if (!xlist.contains(xName)) {
                        xlist.add(xName); //x轴集合不包含即添加
                    }
                }
                index += 1;
            }
            if (ylist != null) {
                if (objs.size() > index) { //列表第二个数据是yAxis
                    if (objs.get(index) == null) { //为空则跳过
                        continue;
                    }
                    yName = objs.get(index).toString();
                    if (!ylist.contains(yName)) {
                        ylist.add(yName); //y轴集合不包含即添加
                    }
                }
                index += 1;
            }
            if (objs.size() == index + 1) { //处理第一/二位为轴，次位为只有一个分组数据的情况
                if (flag) { //因为只有一个分组，固只生成一个集合，方法只执行一次
                    data.put(keySet[1].toString(), new ArrayList<>());
                    flag = false;
                }
                List<Object> temp = data.get(keySet[1].toString()); //取字段名作为唯一分组名
                temp.add(objs.get(index) == null ? "0" : objs.get(index).toString());
            } else if (objs.size() > index + 1) { //处理第一/二位为轴，次位有多个分组数据的情况（基本不出现）
                if (objs.get(index) == null) {
                    continue;
                }
                String str = objs.get(index).toString();
                if (!data.containsKey(str)) {
                    //x轴未出现新的种类，则创立新的分组集合
                    data.put(objs.get(index).toString(), new ArrayList<>());
                }

                List<Object> temp = data.get(str);
                int listSize = temp.size();//已创立数据类型的集合长度，用作判断无数据时补0个数

                int serial = 0;//x轴下标，用作判断无数据时补0个数
                if (xlist != null) {
                    serial = xlist.indexOf(xName);
                } else if (ylist != null) {
                    serial = ylist.indexOf(yName);
                }

                //当集合长度小于x轴下标，则添加对于0数据，但产生相应限制条件，即数据的必须按照x轴顺序插入
                while (serial > 0 && listSize < serial) {
                    temp.add("0");
                    listSize = temp.size();
                }

                temp.add(objs.get(index + 1) == null ? "0" : objs.get(index + 1).toString());
            }

        }

        if (xAxis != null && xlist != null) {
            xAxis.put("data", xlist.toArray());
        }
        if (yAxis != null && ylist != null) {
            yAxis.put("data", ylist.toArray());
        }

        return data;
    }

    /**
     * 将表头keySet作为横、纵坐标
     *
     * @param echarts
     * @param model
     * @return
     */
    private final static LinkedHashMap createByHeaderIsAxis(ECharts echarts, List<Map> model) {
        Map row = model.get(0);
        if (echarts.getOption().getxAxis() != null) {
            Map<String, Object> xAxis = null;
            if (echarts.getOption().getxAxis() instanceof List)
                xAxis = (Map<String, Object>) ((List) echarts.getOption().getxAxis()).get(0);
            else xAxis = (Map<String, Object>) echarts.getOption().getxAxis();
            if ("data".equals(xAxis.get("data"))) {
                Object[] objs = row.keySet().toArray();//获取所有字段名
                if (objs[0] instanceof String)
                    //假设第一列数据为分组，故需要截取一位，可以再开放一个配置项出来，但担心配置项太多没有做,统一截取一位
                    xAxis.put("data", ArrayUtils.subarray(objs, 1, objs.length));
                else
                    xAxis.put("data", objs);
            }
        }
        if (echarts.getOption().getyAxis() != null) {
            Map<String, Object> yAxis = null;
            if (echarts.getOption().getyAxis() instanceof List)
                yAxis = (Map<String, Object>) ((List) echarts.getOption().getyAxis()).get(0);
            else yAxis = (Map<String, Object>) echarts.getOption().getyAxis();
            if ("data".equals(yAxis.get("data"))) {
                Object[] objs = row.keySet().toArray();//获取所有字段名
                if (!(objs[0] instanceof Number))
                    yAxis.put("data", ArrayUtils.subarray(objs, 1, objs.length));
                else
                    yAxis.put("data", objs);
            }
        }
        LinkedHashMap<String, List> data = new LinkedHashMap<>();
        for (Map m : model) {
            Object[] objs = m.values().toArray();
            if (!(objs[0] instanceof Number)) {
                //假设第一列数据为分组，故需要截取一位，可以再开放一个配置项出来，但担心配置项太多没有做,统一截取一位
                data.put(objs[0].toString(), Arrays.asList(ArrayUtils.subarray(objs, 1, objs.length)));
            }
        }

        return data;
    }

    /**
     * 将表头keySet作为分组
     *
     * @param echarts
     * @param model
     * @return
     */
    private final static LinkedHashMap createByHeaderIsKey(ECharts echarts, List<Map> model) {
        Map row = model.get(0);
        int index = 0;
        if (echarts.getOption().getxAxis() != null) {
            Map<String, Object> xAxis = null;
            if (echarts.getOption().getxAxis() instanceof List)
                xAxis = (Map<String, Object>) ((List) echarts.getOption().getxAxis()).get(0);
            else xAxis = (Map<String, Object>) echarts.getOption().getxAxis();
            if ("data".equals(xAxis.get("data"))) {
                Object[] value = (model.get(index)).values().toArray();//获取第一列数据作为x轴
                xAxis.put("data", value);
                index += 1;
            }
        }
        if (echarts.getOption().getyAxis() != null) {
            Map<String, Object> yAxis = null;
            if (echarts.getOption().getyAxis() instanceof List)
                yAxis = (Map<String, Object>) ((List) echarts.getOption().getyAxis()).get(0);
            else yAxis = (Map<String, Object>) echarts.getOption().getyAxis();
            if ("data".equals(yAxis.get("data"))) {
                Object[] value = (model.get(index)).values().toArray();//获取第一列或第二列数据作为y轴
                yAxis.put("data", value);
                index += 1;
            }
        }
        LinkedHashMap<String, List> data = new LinkedHashMap<>();

        Object[] objs = row.keySet().toArray();//获取所有字段名
        for (int i = 0; i < objs.length; i++) {
            List list = new ArrayList();
            for (Map m : model) {
                Object[] value = m.values().toArray();
                list.add(value[index + i]);//取出每一行的的第i个数组成数据集合

            }
            data.put(objs[i].toString(), list);
        }

        return data;
    }

}
